﻿using System;
using System.Runtime.CompilerServices;
using eNets.CBK.Pipe;
using eNets.CBK.Sockets;
using eNets.IO.Memorizer;

namespace eNets.CBK.Session.Tcp;

partial class TcpSession
{
    private const byte SOCKET_WAT = 1;
    private const byte SOCKET_RCV = 2;
    private static readonly int SIZE = MemoryPoolProvider.GetBlockSize() / 2;
    private static readonly Memory<byte> EMPTY = Memory<byte>.Empty;
    
    
    private IPipe<byte> rcvPipe;
    private TcpSocketRcvOper rcvOper;
    
    private IPipeWriter<byte> RcvPipeWriter
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get { return this.rcvPipe.Writer; }
    }

    private void RcvStartAsync()
    {
        WitAsync();
    }

    private void WitAsync()
    {
        this.rcvOper.ValueToken = SOCKET_WAT;
        this.rcvOper.ReceiveAsync(EMPTY);
    }

    private void RcvAsync()
    {
        this.rcvOper.ValueToken = SOCKET_RCV;
        var memory = this.RcvPipeWriter.GetWritableSequence(SIZE);
        this.rcvOper.ReceiveAsync(memory);
    }
    
    private void OnSocketRcvCompleted(in SocketResult result)
    {
        if (!SocketOperationUtil.TryCompleted(result, out var error))
        {
            return;
        }
        
        switch (result.ValueToken)
        {
            case SOCKET_WAT:
                this.RcvAsync();
                break;
            case SOCKET_RCV:
                var bytesReceived = result.Count;
                if (bytesReceived == 0)
                {
                    break;
                }
                this.RcvPipeWriter.WriterAdvance(bytesReceived);
                this.RcvPipeWriter.Flush();
                this.WitAsync();
                break;
        }
    }
}